package com.mall.mymall.filter;


import com.alibaba.fastjson.JSON;
import com.mall.mymall.common.Result;
import com.mall.mymall.dao.dto.AdminDto;
import com.mall.mymall.dao.entity.Administrators;
import com.mall.mymall.dao.entity.Users;
import com.mall.mymall.enums.Roles;
import com.mall.mymall.service.AdministratorsService;
import com.mall.mymall.service.UsersService;
import com.mall.mymall.utils.JwtTokenProvider;
import com.mall.mymall.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;


public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private final JwtTokenProvider jwtProvider;

    private RedisUtils redisUtils;



    private UsersService usersService;


    private AdministratorsService administratorsService;

    public JwtAuthenticationFilter(
            JwtTokenProvider jwtProvider,
            RedisUtils redisUtils,UsersService usersService, AdministratorsService administratorsService) {
        this.administratorsService = administratorsService;
        this.usersService = usersService;
        this.jwtProvider = jwtProvider;
        this.redisUtils = redisUtils;
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        // 检查是否是放行路径
        if (isAllowedPath(requestURI)) {
            filterChain.doFilter(request, response);
            return;
        }
        // 获取 JWT 并验证
        String jwt = getJwtFromRequest(request);
        if (!isValidJwt(jwt)) {
            sendUnauthorizedResponse(response, new Result<>(401, "Invalid or missing JWT token", null));
            return;
        }

        String username = jwtProvider.getUsernameFromToken(jwt);
        if (username == null) {
            sendUnauthorizedResponse(response, new Result<>(401, "Invalid JWT token", null));
            return;
        }

        String userJson = redisUtils.loadUser(username);
        if (userJson == null) {
            Users userByUsername = usersService.getUserByUsername(username);
            if (userByUsername != null) {
                userJson = JSON.toJSONString(userByUsername);
            } else {
                Administrators admin = administratorsService.getAdminByUsername(username);
                if (admin != null) {
                    userJson = JSON.toJSONString(admin);
                } else {
                    sendUnauthorizedResponse(response, new Result<>(401, "User not found", null));
                    return;
                }
            }
        }

        // 获取用户权限
        GrantedAuthority authority = getAuthorityFromUser(userJson);
        if (authority == null) {
            sendUnauthorizedResponse(response, new Result<>(401, "User has no authority", null));
            return;
        }
        setAuthenticationContext(username, authority, request);
        filterChain.doFilter(request, response);
    }

    private void setAuthenticationContext(String username, GrantedAuthority authority, HttpServletRequest request) {
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                username, null, Collections.singletonList(authority)
        );
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    private GrantedAuthority getAuthorityFromUser(String userJson) {
        try {
            AdminDto admin = JSON.parseObject(userJson, AdminDto.class);
            return Roles.toGrantedAuthority(Roles.values()[admin.getRoleId() - 1].getAuthority());
        } catch (Exception e) {
            try {

                Users user = JSON.parseObject(userJson, Users.class);
                return Roles.toGrantedAuthority(Roles.values()[user.getRoleId() - 1].getAuthority());
            } catch (Exception ex) {
                System.out.println(ex.getMessage() + "\n" + e.getMessage());
            }

        }
        return null;
    }

    private boolean isValidJwt(String jwt) {
        return jwt != null && jwtProvider.validateToken(jwt);
    }

    private boolean isAllowedPath(String requestURI) {
        Set<String> allowedPaths = new HashSet<>();
        allowedPaths.add("/administrators/login");
        allowedPaths.add("/users");
        allowedPaths.add("/users/register");
        allowedPaths.add("/adminAvatar");
        allowedPaths.add("/product");
        return allowedPaths.stream().anyMatch(path -> requestURI.startsWith(path));
    }

    private String getJwtFromRequest(HttpServletRequest request) {
        // 截取请求头的Authorization 字符串
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }

    private void sendUnauthorizedResponse(HttpServletResponse response, Result<?> result) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().write(JSON.toJSONString(result));
    }
}
